package com.elitect.ftptransfer.network;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import android.content.Context;
import android.net.ConnectivityManager;

import com.elitect.ftptransfer.module.main.data.FileItem;

/**
 * The class for network connections
 * 
 * @author NgocTan
 * 
 */
public final class NetworkUtils
{
    private static FTPClient sFtpClient = new FTPClient();
    private static OnFTPConnectListener mOnNetworkListener;

    private NetworkUtils()
    {
    }

    public static void setOnNetworkListener(OnFTPConnectListener listener)
    {
        mOnNetworkListener = listener;
    }

    /**
     * Do FTP connect.
     * 
     * @param server
     * @param port
     */
    public static void doFtpConnect(final String server, final int port)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    if (port == -1)
                    {
                        sFtpClient.connect(server);
                    }
                    else
                    {
                        sFtpClient.connect(server, port);
                    }

                    if (FTPReply.isPositiveCompletion(sFtpClient.getReplyCode()))
                    {
                        sFtpClient.enterLocalPassiveMode();
                        mOnNetworkListener.onFtpConnectSuccess();
                        return;
                    }
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpConnectFail();
            }
        }).start();
    }

    /**
     * Do FTP login.
     * 
     * @param username
     * @param password
     */
    public static void doFtpLogin(final String username, final String password)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    if (sFtpClient.login(username, password))
                    {
                        mOnNetworkListener.onFtpLoginSuccess();
                        return;
                    }
                    else
                    {
                        sFtpClient.logout();
                    }
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpLoginFail();
            }
        }).start();
    }

    /**
     * Do FTP load files from the server path name
     * 
     * @param path
     */
    public static void doFtpLoadFiles(final String path)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                if (!sFtpClient.isConnected())
                {
                    mOnNetworkListener.onFtpLoadFilesFail();
                    return;
                }

                sFtpClient.enterLocalPassiveMode();

                try
                {
                    mOnNetworkListener.onFtpLoadedFiles(path,
                            sFtpClient.listFiles(path));
                    return;
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpLoadFilesFail();
            }
        }).start();
    }

    public static void doFtpLogout()
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    if (sFtpClient.isConnected())
                    {
                        sFtpClient.logout();
                        sFtpClient.disconnect();
                    }
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * Do upload files to server at current directory
     * 
     * @param fileItems
     */
    public static void doFtpUploadFiles(final List<FileItem> fileItems,
            final String path)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                if (!sFtpClient.isConnected())
                {
                    mOnNetworkListener.onFtpUploadFailAll();
                    return;
                }

                try
                {
                    sFtpClient.changeWorkingDirectory(path);
                } catch (IOException e)
                {
                    e.printStackTrace();
                    mOnNetworkListener.onFtpUploadFailAll();
                    return;
                }

                List<String> listSucessUploadFiles = new ArrayList<String>();
                List<String> listFailUploadFiles = new ArrayList<String>();
                for (FileItem fileItem : fileItems)
                {
                    if (!fileItem.isFile())
                    {
                        continue;
                    }
                    FileInputStream srcFileStream = null;
                    try
                    {
                        srcFileStream = new FileInputStream(new File(
                                fileItem.getFullPath()));
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                        continue;
                    }

                    try
                    {
                        boolean isSuccess = sFtpClient.storeFile(
                                fileItem.getName(), srcFileStream);
                        if (isSuccess)
                        {
                            listSucessUploadFiles.add(fileItem.getName());
                        }
                        else
                        {
                            listFailUploadFiles.add(fileItem.getName());
                        }
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                        listFailUploadFiles.add(fileItem.getName());
                    }

                    try
                    {
                        srcFileStream.close();
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }

                try
                {
                    sFtpClient.changeWorkingDirectory("/");
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpUploaded(listSucessUploadFiles,
                        listFailUploadFiles);
            }
        }).start();
    }

    /**
     * Do download files from server and save to the local path
     * 
     * @param fileItems
     * @param pathSave
     */
    public static void doFtpDownloadFiles(final List<FileItem> fileItems,
            final String pathNameServer, final String pathSave)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                if (!sFtpClient.isConnected())
                {
                    mOnNetworkListener.onFtpDownloadFailAll();
                    return;
                }
                try
                {
                    sFtpClient.changeWorkingDirectory(pathNameServer);
                } catch (IOException e)
                {
                    e.printStackTrace();
                    mOnNetworkListener.onFtpDownloadFailAll();
                    return;
                }

                List<String> listSucessDownloadFiles = new ArrayList<String>();
                List<String> listFailDownloadFiles = new ArrayList<String>();
                for (FileItem fileItem : fileItems)
                {
                    if (!fileItem.isFile())
                    {
                        continue;
                    }
                    FileOutputStream srcFileStream = null;
                    try
                    {
                        srcFileStream = new FileOutputStream(new File(pathSave
                                + fileItem.getName()));
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                        continue;
                    }

                    try
                    {
                        boolean isSuccess = sFtpClient.retrieveFile(
                                fileItem.getName(), srcFileStream);
                        if (isSuccess)
                        {
                            listSucessDownloadFiles.add(fileItem.getName());
                        }
                        else
                        {
                            listFailDownloadFiles.add(fileItem.getName());
                        }
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                        listFailDownloadFiles.add(fileItem.getName());
                    }

                    try
                    {
                        srcFileStream.close();
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }

                try
                {
                    sFtpClient.changeWorkingDirectory("/");
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpDownloaded(listSucessDownloadFiles,
                        listFailDownloadFiles);
            }
        }).start();
    }

    /**
     * Do create new folder
     * 
     * @param folderName
     */
    public static void doFtpCreateNewFolder(final String pathNameServer,
            final String folderName)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    if (!sFtpClient.isConnected())
                    {
                        mOnNetworkListener.onFtpCreateFolderFail();
                        return;
                    }
                    sFtpClient.changeWorkingDirectory(pathNameServer);
                    boolean isSuccess = sFtpClient.makeDirectory(folderName);
                    sFtpClient.changeWorkingDirectory("/");
                    if (isSuccess)
                    {
                        mOnNetworkListener.onFtpCreateFolderSuccessful();
                        return;
                    }

                } catch (IOException e)
                {
                    e.printStackTrace();
                }
                mOnNetworkListener.onFtpCreateFolderFail();
            }
        }).start();
    }

    public static void doFtpCheckConnection()
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                while (true)
                {
                    try
                    {
                        Thread.sleep(1000);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }

                    if (!sFtpClient.isConnected())
                    {
                        mOnNetworkListener.onFtpDisconnect();
                        break;
                    }
                }
            }
        }).start();
    }

    public static boolean isNetworkAvailable(Context context)
    {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return connectivityManager.getActiveNetworkInfo() != null;
    }
}
